#include <botan-2/botan/filters.h>
#include <botan-2/botan/hex.h>
#include <botan/botan.h>
#include <botan/hex.h>
#include <cstdint>
#include <iostream>
#include <vector>
using namespace std;

void test_block_cipher()
{
    std::vector<uint8_t> key    = Botan::hex_decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F");
    std::vector<uint8_t> block  = Botan::hex_decode("00112233445566778899AABBCCDDEEFF");
    const auto           cipher = Botan::BlockCipher::create_or_throw("AES-256");
    cipher->set_key(key);
    cipher->encrypt(block);
    std::cout << cipher->name() << " single block encrypt: " << Botan::hex_encode(block) << std::endl;
    cipher->decrypt(block);
    std::cout << cipher->name() << " single block decrypt: " << Botan::hex_encode(block) << std::endl;

    // clear cipher for 2nd encryption with other key
    cipher->clear();
    key = Botan::hex_decode("1337133713371337133713371337133713371337133713371337133713371337");
    cipher->set_key(key);
    cipher->encrypt(block);

    std::cout << cipher->name() << " single block encrypt: " << Botan::hex_encode(block) << std::endl;
}

std::string test_encode(const std::string &key, const std::string &iv, const std::string &message)
{
    std::vector<uint8_t> cipher_key(key.data(), key.data() + key.length());
    std::vector<uint8_t> cipher_iv = Botan::hex_decode(iv);

    auto encryptCipher = Botan::Cipher_Mode::create("AES-128/CFB(8)", Botan::ENCRYPTION);
    encryptCipher->set_key(cipher_key);
    encryptCipher->start(cipher_iv);

    Botan::secure_vector<uint8_t> vecEncMsg(message.data(), message.data() + message.length());
    encryptCipher->finish(vecEncMsg);
    std::string strEncryptText = Botan::hex_encode(vecEncMsg);

    std::transform(strEncryptText.begin(), strEncryptText.end(), strEncryptText.begin(), ::tolower);
    return strEncryptText;
}

std::string test_decode(const std::string &key, const std::string &iv, const std::string &encryptText)
{
    std::vector<uint8_t> cipher_key(key.data(), key.data() + key.length());
    auto                 cipher_iv     = Botan::hex_decode(iv);
    auto                 decryptCipher = Botan::Cipher_Mode::create("AES-128/CFB(8)", Botan::DECRYPTION);
    decryptCipher->set_key(cipher_key);
    decryptCipher->start(cipher_iv);

    auto vecEncMsg = Botan::hex_decode_locked(encryptText);
    decryptCipher->finish(vecEncMsg);

    std::string strPlainText(vecEncMsg.begin(), vecEncMsg.end());
    return strPlainText;
}

int main(int argc, char *argv[])
{
    std::string key = "thisisacipherkey";
    std::string iv  = "1A2B3C4D5E6F1A2B3C4D5E6F12345678";
    std::string msg = "Hello, World!";

    std::string strEncryptText = test_encode(key, iv, msg);
    std::cout << "strEncryptText: " << strEncryptText << std::endl;

    std::string strPlainText = test_decode(key, iv, strEncryptText);
    std::cout << "strPlainText: " << strPlainText << std::endl;
    return 0;
}
